package com.dymall.api.client.fallback;

import com.dymall.common.utils.CollUtils;
import com.dymall.api.client.ItemClient;
import com.dymall.api.dto.ItemDTO;
import com.dymall.api.dto.OrderDetailDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;

import java.util.Collection;
import java.util.List;

@Slf4j
public class ItemClientFallbackFactory implements FallbackFactory<ItemClient> {
    /*
    这里在做线程隔离时，对整个购物车逻辑做流量控制(请求限流、线程隔离)、服务熔断，在高并发的情况下，会影响其他业务的执行。
    这里建议只对查购物车的逻辑做线程隔离。
    将服务中的openfeign调用注册到sentinel中，当因流量控制(请求限流、线程隔离)、服务熔断等原因报错时通过编写fallback逻辑返回友好提示或者空信息。

    因为cartservice微服务远程调用了itemclient逻辑，在这里编写相关的fallback逻辑
    1、配置：开启sentinel流量控制，将feignclient作为sentinel的簇点资源
    2、编写相关的fallback逻辑
    3、将定义好的ItemClientFallbackFactory注册为一个Bean对象
    4、在ItemClient接口中调用ItemClientFallbackFactory
     */
    @Override
    public ItemClient create(Throwable cause) {//远程调用或限流产生的异常
        return new ItemClient() {
            @Override
            public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
                log.error("远程调用ItemClient#queryItemByIds方法出现异常，参数：{}", ids, cause);
                // 查询购物车允许失败，查询失败，返回空集合
                return CollUtils.emptyList();//返回空列表
            }

            @Override
            public void deductStock(Collection<OrderDetailDTO> items) {
                log.error("扣减商品库存失败", cause);
                // 库存扣减业务需要触发事务回滚，查询失败，抛出异常
                throw new RuntimeException(cause);
            }
        };
    }
}
